home *** CD-ROM | disk | FTP | other *** search
/ Power Programmierung / Power-Programmierung (Tewi)(1994).iso / magazine / msysjour / vol05 / 05 / swap / exec.c < prev    next >
C/C++ Source or Header  |  1990-09-01  |  9KB  |  333 lines

  1. /*
  2.    EXEC function with memory swap.
  3.    Needs Assembler file 'spawn.asm'.
  4.  
  5. Public domain software by
  6.  
  7.         Thomas Wagner
  8.         Ferrari electronic GmbH
  9.         Beusselstrasse 27
  10.         D-1000 Berlin 21
  11.         West Germany
  12.  
  13.         BIXname: twagner
  14. */
  15.  
  16. #include "compat.h"
  17. #include <ctype.h>
  18.  
  19. extern int do_exec (char *xfn, char *pars, int spwn, unsigned needed,
  20.                           char **envp);
  21.  
  22. /*
  23.    The EXEC function.
  24.  
  25.       Parameters:    xfn   is a string containing the name of the file
  26.                            to be executed. If the string is empty,
  27.                            the COMSPEC environment variable is used to
  28.                            load a copy of COMMAND.COM or its equivalent.
  29.                            If the filename does not include a path, the
  30.                            current PATH is searched after the default.
  31.                            If the filename does not include an extension,
  32.                            the path is scanned for a COM or EXE file in
  33.                            that order.
  34.  
  35.                      pars  The program parameters.
  36.  
  37.                      spwn  If 1, the function will return, if necessary
  38.                            after swapping the memory image. 
  39.                            If -1, EMS will not be used when swapping.
  40.                            If 0, the function will terminate after the 
  41.                            EXECed program returns. 
  42.                            NOTE: If the program file is not found, 
  43.                            the function will always return
  44.                            with the appropriate error code, even if 
  45.                            'spwn' is 0.
  46.  
  47.                      needed   The memory needed for the program in 
  48.                            paragraphs. If not enough memory is free, the
  49.                            program will be swapped out. Use 0 to never
  50.                            swap, 0xffff to always swap. If 'spwn' is false,
  51.                            this parameter is irrelevant.
  52.  
  53.                      envp  The environment to be passed to the spawned
  54.                            program. If this parameter is NULL, a copy
  55.                            of the parent's environment is used (i.e.
  56.                            'putenv' calls have no effect). If non-NULL,
  57.                            envp must point to an array of pointers to
  58.                            strings, terminated by a NULL pointer (the
  59.                            standard variable 'environ' may be used).
  60.  
  61.       Return value:
  62.                            0x0000..00FF: The EXECed Program's return code
  63.                            (0..255 decimal)
  64.                            0x0100:       Error writing swap file
  65.                            (256 decimal)
  66.                            0x0200:       Program file not found
  67.                            (512 decimal)
  68.                            0x03xx:       DOS-error-code xx calling EXEC
  69.                            (768..1023 decimal)
  70.                            0x0400:       Error allocating environment buffer
  71.                            (1024 decimal)
  72. */
  73.  
  74.  
  75. #define SWAP_FILENAME "$$AAAAAA.AAA" 
  76.  
  77. #define M_SWAPPING   0x01
  78. #define M_USE_EMS    0x02
  79. #define M_CREAT_TEMP 0x04
  80. #define M_EXEC       0x80
  81.  
  82.  
  83. extern int do_spawn (unsigned char method, 
  84.                      char *swapfn, char *xeqfn, char *cmdtail, 
  85.                      unsigned envlen, char *envp);
  86.  
  87.  
  88. int exists (char *fn)
  89.  
  90.    /* Returns TRUE if a file with name 'fn' exists. */
  91.  
  92. {
  93.    struct ffblk fb;
  94.  
  95.    return !findfirst (fn, 
  96.                       &fb, 
  97.                       FA_RDONLY | FA_HIDDEN | FA_SYSTEM | FA_ARCH);
  98. }
  99.  
  100.  
  101. int tryext (char *fn)
  102.  
  103.    /* Try '.COM' and '.EXE' on current filename, modify filename if found. */
  104.  
  105. {
  106.     int i;
  107.  
  108.    i = strlen (fn);
  109.    strcat (fn, ".COM");
  110.    if (exists (fn))
  111.       return 1;
  112.    fn [i] = 0;
  113.    strcat (fn, ".EXE");
  114.    if (exists (fn))
  115.       return 1;
  116.    fn [i] = 0;
  117.    return 0;
  118. }
  119.  
  120.  
  121. int findfile (char *fn)
  122.  
  123.    /* Try to find the file 'fn' in the current path. Modifies the filename
  124.       accordingly. */
  125.  
  126. {
  127.    char path [256];
  128.    char *prfx;
  129.    int found;
  130.    char drive [MAXDRIVE], dir [MAXDIR], name [MAXFILE], ext [MAXEXT];
  131.  
  132.    if (!fn [0])
  133.       strcpy (fn, getenv ("COMSPEC"));
  134.  
  135.    fnsplit (fn, drive, dir, name, ext);
  136.  
  137.    if (ext [0])
  138.       found = exists (fn);
  139.    else
  140.       found = tryext (fn);
  141.  
  142.    if (!found && !dir [0] && !drive [0])
  143.       {
  144.         strcpy (path, getenv ("PATH"));
  145.       prfx = strtok (path, ";");
  146.  
  147.       while (!found && prfx != NULL)
  148.          {
  149.          fnmerge (fn, drive, prfx, name, ext);
  150.          if (ext [0])
  151.             found = exists (fn);
  152.          else
  153.             found = tryext (fn);
  154.  
  155.          prfx = strtok (NULL, ";");
  156.          }
  157.         }
  158.    return found;
  159. }
  160.  
  161.  
  162. /*
  163.    tempdir: Set temporary file path.
  164.             Read "TMP/TEMP" environment. If empty or invalid, clear path.
  165.             If TEMP is drive or drive+backslash only, return TEMP.
  166.             Otherwise check if given path is a valid directory.
  167.             If so, add a backslash, else clear path.
  168. */
  169.  
  170. void tempdir (char *outfn)
  171. {
  172.     int l;
  173.    char drive [MAXDRIVE], dir [MAXDIR];
  174.     char name [MAXFILE], ext [MAXEXT];
  175.    char *s;
  176.    struct stat ff;
  177.    union REGS regs;
  178.    struct SREGS segregs;
  179.  
  180.    *outfn = 0;
  181.    if ((s = getenv ("TMP")) == NULL)
  182.       if ((s = getenv ("TEMP")) == NULL)
  183.          return;
  184.  
  185.    strcpy (outfn, s);
  186.    l = strlen (outfn);
  187.    if (!l)
  188.       return;
  189.  
  190.    if (outfn [l - 1] == '\\' || outfn [l - 1] == '/')
  191.       outfn [--l] = 0;
  192.  
  193.    fnsplit (outfn, drive, dir, name, ext);
  194.  
  195.    if (drive [0])
  196.       {
  197.       regs.h.dl = toupper (drive [0]) - 'A' + 1;
  198.       regs.h.ah = 0x1c;
  199.       intdosx (®s, ®s, &segregs);
  200.       if (regs.h.al == 0xff)
  201.          {
  202.          *outfn = 0;
  203.          return;
  204.          }
  205.       }
  206.  
  207.    if (!name [0])   /* No dir name */
  208.       {
  209.       if (dir [0])
  210.          *outfn = 0;
  211.       else
  212.          {
  213.             outfn [l++] = '\\';
  214.          outfn [l] = 0;
  215.          }
  216.       return;
  217.       }
  218.  
  219.    if (stat (outfn, &ff))
  220.       *outfn = 0;
  221.    else if (!(ff.st_mode & S_IFDIR) || !(ff.st_mode & S_IWRITE))
  222.       *outfn = 0;
  223.    else
  224.       {
  225.       outfn [l++] = '\\';
  226.       outfn [l] = 0;
  227.       }
  228. }
  229.  
  230.  
  231. int do_exec (char *exfn, char *epars, int spwn, unsigned needed, char **envp)
  232. {
  233.    char swapfn [80];
  234.    char xfbuf [80];
  235.     char *xfn;
  236.     char pars [130];
  237.    unsigned avail;
  238.    union REGS regs;
  239.    unsigned envlen, rc;
  240.    int idx;
  241.    char **env;
  242.    char *ep, *envbuf;
  243.    unsigned char method;
  244.  
  245.     xfn = &xfbuf [1];
  246.    strcpy (xfn, exfn);
  247.    strcpy (&pars [1], epars);
  248.    pars [0] = (char)strlen (epars);
  249.  
  250.    /* First, check if the file to execute exists. */
  251.  
  252.    if (!findfile (xfn))
  253.       return 0x200;
  254.  
  255.    /* Now create a copy of the environment if the user wants it. */
  256.  
  257.    envlen = 0;
  258.    if (envp != NULL)
  259.       for (env = envp; *env != NULL; env++)
  260.          envlen += strlen (*env) + 1;
  261.  
  262.    if (envlen)
  263.       {
  264.       envlen++;
  265.       ep = envbuf = malloc (envlen);
  266.       if (envbuf == NULL)
  267.          return 0x400;
  268.       for (env = envp; *env != NULL; env++)
  269.          {
  270.          ep = stpcpy (ep, *env) + 1;
  271.          }
  272.       *ep = 0;
  273.       }
  274.  
  275.  
  276.     xfbuf [0] = (char)strlen (xfn);
  277.  
  278.    if (!spwn)
  279.       method = M_EXEC;    /* Mark 'EXEC' function */
  280.    else
  281.       {
  282.       /* Determine amount of free memory */
  283.         regs.x.ax = 0x4800;
  284.         regs.x.bx = 0xffff;
  285.       intdos (®s, ®s);
  286.         avail = regs.x.bx;
  287.  
  288.       /* No swapping if available memory > needed */
  289.  
  290.       if (needed < avail)
  291.          method = 0;
  292.       else
  293.          {
  294.          /* Swapping necessary, use 'TMP' or 'TEMP' environment variable
  295.            to determine swap file path if defined. */
  296.  
  297.          method = (unsigned char)
  298.                   ((spwn < 0) ? M_SWAPPING : M_SWAPPING | M_USE_EMS);
  299.  
  300.          swapfn [0] = 1; /* dummy length byte */
  301.          tempdir (&swapfn [1]);
  302.  
  303.          if (OS_MAJOR >= 3)
  304.             method |= M_CREAT_TEMP;
  305.          else
  306.             {
  307.             strcat (swapfn, SWAP_FILENAME);
  308.             idx = strlen (swapfn) - 1;
  309.             while (exists (swapfn))
  310.                {
  311.                if (swapfn [idx] == 'Z')
  312.                   idx--;
  313.                if (swapfn [idx] == '.')
  314.                   idx--;
  315.                swapfn [idx]++;
  316.                }
  317.             }
  318.          }
  319.         }
  320.  
  321.    /* All set up, ready to go. */
  322.  
  323.    rc = do_spawn (method, swapfn, xfbuf, pars, envlen, envbuf);
  324.  
  325.    /* Free the environment buffer if it was allocated. */
  326.  
  327.    if (envlen)
  328.       free (envbuf);
  329.  
  330.    return rc;
  331. }
  332.  
  333.